﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Workbench.Models;
using Workbench.Operations;
using Workbench.Presentation.UserContols;
using Workbench.Shared;

namespace Workbench.Presentation
{
    public class ExercisesViewModel : TabViewModelBase
    {
        public ExercisesViewModel()
            : base("Course Development")
        {
            //ExerciseSuites.Add(new ExerciseSuiteModel() { Name = "Control work 1" });
            //ExerciseSuites.Add(new ExerciseSuiteModel() { Name = "Control work 2" });

            //Exercises.Add(new ConcordancerExerciseModel() { Name = "Exercise 1" });
            //Exercises.Add(new ConcordancerExerciseModel() { Name = "Exercise 2" });

            ExerciseSuites.SubscribeItemPropChange<ExerciseSuiteViewModel>("IsSelected", ExerciseSuites_IsSelectedChanged);
            Exercises.SubscribeItemPropChange<ConcordancerExerciseViewModel>("IsSelected", Exercise_IsSelectedChanged);
            this.PropertyChanged += ExercisesViewModel_PropertyChanged;

            this.addConcordancerExercise = new _AddConcordancerExercise(this);
            this.removeExercise = new _RemoveExercise(this);
            this.addSuite = new _AddSuite(this);
            this.removeSuite = new _RemoveSuite(this);
        }

        #region Commands

        #region AddSuite

        readonly _AddSuite addSuite;
        public ICommand AddSuite
        {
            get { return addSuite; }
        }

        private class _AddSuite : ICommand
        {
            readonly ExercisesViewModel viewModel;

            public _AddSuite(ExercisesViewModel viewModel)
            {
                this.viewModel = viewModel;
            }

            void RaiseCanExecuteChanged()
            {
                this.CanExecuteChanged(null, EventArgs.Empty);
            }

            public bool CanExecute(object parameter)
            {
                return true;
            }

            public void Execute(object parameter)
            {
                var result = PromptDialog.Prompt(MainWindow.AppWindow, "Enter the name of the new suite", "New Exercise Suite");
                if (!string.IsNullOrWhiteSpace(result))
                {
                    var suite = ExerciseOperations.CreateTestSuite(result);
                    viewModel.ExerciseSuites.Add(new ExerciseSuiteViewModel(suite));
                } 
            }

            public event EventHandler CanExecuteChanged = (sender, args) => { };
        }

        #endregion AddSuite

        #region RemoveSuite

        readonly _RemoveSuite removeSuite;
        public ICommand RemoveSuite
        {
            get { return removeSuite; }
        }

        private class _RemoveSuite : ICommand
        {
            readonly ExercisesViewModel viewModel;

            public _RemoveSuite(ExercisesViewModel viewModel)
            {
                this.viewModel = viewModel;
                this.viewModel.PropertyChanged += viewModel_PropertyChanged;
            }

            void viewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                if (string.Compare(e.PropertyName, "SelectedExerciseSuite") == 0)
                    RaiseCanExecuteChanged();
            }

            void RaiseCanExecuteChanged()
            {
                this.CanExecuteChanged(null, EventArgs.Empty);
            }

            public bool CanExecute(object parameter)
            {
                return viewModel.SelectedExerciseSuite != null;
            }

            public void Execute(object parameter)
            {
                var vm = viewModel.SelectedExerciseSuite;
                ExerciseOperations.DeleteExerciseSuite(vm.DataModel);
                viewModel.ExerciseSuites.Remove(vm);
                viewModel.SelectedExerciseSuite = null;
            }

            public event EventHandler CanExecuteChanged = (sender, args) => { };
        }

        #endregion RemoveSuite

        #region AddConcordancerExercise

        readonly _AddConcordancerExercise addConcordancerExercise;
        public ICommand AddConcordancerExercise
        {
            get { return addConcordancerExercise; }
        }

        private class _AddConcordancerExercise : ICommand
        {
            readonly ExercisesViewModel viewModel;

            public _AddConcordancerExercise(ExercisesViewModel viewModel)
            {
                this.viewModel = viewModel;
                this.viewModel.PropertyChanged += viewModel_PropertyChanged;
            }

            void viewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                if (string.Compare(e.PropertyName, "SelectedExerciseSuite") == 0)
                    RaiseCanExecuteChanged();
            }

            void RaiseCanExecuteChanged()
            {
                this.CanExecuteChanged(null, EventArgs.Empty);
            }

            public bool CanExecute(object parameter)
            {
                return viewModel.SelectedExerciseSuite != null;
            }

            public void Execute(object parameter)
            {
                var dialog = new ConcordancerExerciseDialog() { DataContext = new ConcordancerViewModel() };
                var result = dialog.ShowDialog();
                if (result.HasValue && result.Value == true)
                {
                    var dialogViewModel = ((ConcordancerViewModel)dialog.DataContext);
                    if (dialogViewModel.Words.Count > 0)
                    {
                        var a = dialogViewModel.Words.Where(x => x.IsSelected).Select(x => x.DataModel).ToList();
                        if (a.Count == 0) a = dialogViewModel.Words.Select(x => x.DataModel).ToList();
                        if (a.Count == 0) return;

                        var b = dialogViewModel.SelectedWordSuggestion.DataModel;
                        var exercise = ExerciseOperations.CreateConcordancerExercise(a, b);
                        ExerciseOperations.AddToSuite(viewModel.SelectedExerciseSuite.DataModel, exercise);
                        viewModel.ReloadExercises();
                    }
                }
            }

            public event EventHandler CanExecuteChanged = (sender, args) => { };
        }

        #endregion AddConcordancerExercise

        #region RemoveExercise

        readonly _RemoveExercise removeExercise;
        public ICommand RemoveExercise
        {
            get { return removeExercise; }
        }

        private class _RemoveExercise : ICommand
        {
            readonly ExercisesViewModel viewModel;

            public _RemoveExercise(ExercisesViewModel viewModel)
            {
                this.viewModel = viewModel;
                if (this.viewModel != null) this.viewModel.PropertyChanged += viewModel_PropertyChanged;
            }

            void RaiseCanExecuteChanged()
            {
                this.CanExecuteChanged(null, EventArgs.Empty);
            }

            public bool CanExecute(object parameter)
            {
                return viewModel.SelectedExercise != null;
            }

            public void Execute(object parameter)
            {
                ExerciseOperations.DeleteConcordancerExercise(viewModel.SelectedExercise.DataModel);
                viewModel.Exercises.Remove(viewModel.SelectedExercise);
                viewModel.SelectedExercise = null;
            }

            void viewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
            {
                if (string.Compare(e.PropertyName, "SelectedExercise", true) == 0)
                {
                    RaiseCanExecuteChanged();
                }
            }

            public event EventHandler CanExecuteChanged = (sender, args) => { };
        }

        #endregion RemoveExercise

        #endregion

        #region Event Handlers

        void ExercisesViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "SelectedExerciseSuite":
                {
                    if (SelectedExerciseSuite != null)
                    {
                        LoadExercises(SelectedExerciseSuite.DataModel); 
                    }
                    break;
                }
            }
        }
        private void ExerciseSuites_IsSelectedChanged(ExerciseSuiteViewModel suiteViewModel)
        {
            if (suiteViewModel.IsSelected) SelectedExerciseSuite = suiteViewModel;
        }
        private void Exercise_IsSelectedChanged(ConcordancerExerciseViewModel exerciseViewModel)
        {
            if (exerciseViewModel.IsSelected) SelectedExercise = exerciseViewModel;
        }

        #endregion

        #region Properties

        private ExerciseSuiteViewModel selectedExerciseSuite;
        public ExerciseSuiteViewModel SelectedExerciseSuite
        {
            get { return selectedExerciseSuite; }
            set { selectedExerciseSuite = value; RaisePropertyChanged(); }
        }

        private ConcordancerExerciseViewModel selectedExercise;
        public ConcordancerExerciseViewModel SelectedExercise
        {
            get { return selectedExercise; }
            set { selectedExercise = value; RaisePropertyChanged(); }
        }

        private ObservableCollection<ExerciseSuiteViewModel> exerciseSuites = new ObservableCollection<ExerciseSuiteViewModel>();
        public ObservableCollection<ExerciseSuiteViewModel> ExerciseSuites
        {
            get { return exerciseSuites; }
        }

        private ObservableCollection<ConcordancerExerciseViewModel> exercises = new ObservableCollection<ConcordancerExerciseViewModel>();
        public ObservableCollection<ConcordancerExerciseViewModel> Exercises
        {
            get { return exercises; }
        }

        #endregion

        #region Life Cycle
        public override void Load()
        {
            var suites = ExerciseOperations.GetTestSuites().Select(x => new ExerciseSuiteViewModel(x));
            ExerciseSuites.AddRange(suites);
        }

        public override void Unload()
        {
            ExerciseSuites.Clear();
            Exercises.Clear();
        }

        private void LoadExercises(ExerciseSuiteModel suiteModel)
        {
            var exerciseViewModels = ExerciseOperations.GetExercises(suiteModel).Select(x => new ConcordancerExerciseViewModel(x)).ToArray();
            foreach (var exerciseViewModel in exerciseViewModels)
            {
                exerciseViewModel.SentencesPlain = ExerciseOperations.ExportAsText(exerciseViewModel.DataModel);
            }
            Exercises.Clear();
            Exercises.AddRange(exerciseViewModels);
        }

        private void ReloadExercises()
        {
            if (SelectedExerciseSuite != null)
            {
                LoadExercises(SelectedExerciseSuite.DataModel);
            }
        }
        #endregion

    }
}
